home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
strategy
/
vga_card.000
/
vga_cardgames-1.3.1.tar
/
vga_cardgames
/
spider.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-25
|
10KB
|
578 lines
/*
* Spider
*
* Copyright (C) Evan Harris, 1991, 1993, 1994
*
* Permission is granted to freely redistribute and modify this code,
* providing the author(s) get credit for having written it.
*/
#include "spider.h"
#include <stdlib.h>
#define U_MOVE 1
#define U_MOVEOFF 2
#define U_MOVE_EXPOSE 3
#define U_MOVEOFF_EXPOSE 4
#define U_FROMSTOCK 5
struct undo {
unsigned char type;
unsigned char card;
short from;
struct undo *next;
};
unsigned char column[COLUMNS]; /* First card of column */
unsigned char stock;
short cards[NUMCARDS]; /* Positions of cards */
unsigned char next[NUMCARDS]; /* Card underneath */
unsigned char hidden[NUMCARDS]; /* Cards which are face down */
unsigned char foundation[NUMSUITS];
struct undo *undoinfo = NULL;
void main(int argc, char **argv)
{
short cmd, dest;
InitDisplay(argc, argv);
InitRandom(NEW);
Deal();
for (;;) {
cmd = GetCmd();
if (cmd == QUIT) {
EndDisplay();
exit(0);
}
else if (cmd == NEWGAME) {
InitRandom(NEW);
Deal();
}
else if (cmd == RESTART) {
InitRandom(LAST);
Deal();
}
else if (cmd == FROMSTOCK) {
FromStock();
}
else if (cmd == UNDO) {
Undo();
}
else if (ISCARD(NOHINT(cmd))) {
dest = FindDest(cmd);
if (dest != NOPOSN)
MakeMove((unsigned char)NOHINT(cmd), dest);
}
}
/* Never reached */
}
void Deal()
{
unsigned char i, j;
unsigned char row, col;
short r, lastr = 0;
struct undo *u;
/* Initialise the deck */
for (i = 0; i < NUMCARDS; i++) {
cards[i] = NOPOSN;
next[i] = NOCARD;
}
/* Initialise foundations */
for (i = 0; i < NUMSUITS; i++) {
foundation[i] = 0;
}
/* Remove undo information */
while (undoinfo) {
u = undoinfo->next;
free(undoinfo);
undoinfo = u;
}
/* Deal the deck */
row = 0;
col = 0;
for (i = 0; i < NUMCARDS; i++) {
r = Random(NUMCARDS - i);
for (j = 0; j < NUMCARDS && r >= 0; j++) {
if (cards[j] == NOPOSN)
r--;
}
r = j - 1;
cards[r] = POSN(col, row);
if (col != STOCK) {
if (row == 0)
column[col] = r;
else
next[lastr] = r;
lastr = r;
if ((col < 4 && row < 5) || (row < 4)) {
hidden[r] = 1;
row++;
}
else {
hidden[r] = 0;
col++;
row = 0;
}
}
else {
if (row == 0)
stock = r;
else
next[lastr] = r;
lastr = r;
hidden[r] = 0;
row++;
}
}
for (i = 0; i < COLUMNS; i++)
DisplayColumn((short)i);
DisplayFoundations();
DisplayStockPile();
return;
}
short FindDest(short card)
{
unsigned char i, c;
short first = -1;
c = next[NOHINT(card)];
i = 1;
while (c != NOCARD) {
if (SUIT(c) != SUIT(NOHINT(card)) || TYPE(c) != TYPE(NOHINT(card)) - i) {
return NOPOSN;
}
c = next[c];
i++;
}
if (HASHINT(card))
return FindHintedDest((short)NOHINT(card), (short)HINT(card));
if (CanMoveOff((unsigned char)card))
return MOVEOFF;
c = column[COL(cards[card])];
if (c != card) {
while (next[c] != card)
c = next[c];
if (!hidden[c] && TYPE(c) == TYPE(card) + 1 && SUIT(c) == SUIT(card)) {
return NOPOSN;
}
}
if (TYPE(card) != KING) {
for (i = 0; i < COLUMNS; i++) {
if (i != COL(cards[card]) && column[i] != NOCARD) {
c = column[i];
while (next[c] != NOCARD)
c = next[c];
if (TYPE(c) == TYPE(card) + 1) {
if (SUIT(c) == SUIT(card)) {
return (short)POSN(COL(cards[c]), ROW(cards[c]) + 1);
}
else if (first == -1)
first = c;
}
}
}
if (first != -1) {
return (short)POSN(COL(cards[first]), ROW(cards[first]) + 1);
}
}
if (ROW(cards[card]) == 0) {
return NOPOSN;
}
for (i = 0; i < COLUMNS; i++) {
if (column[i] == NOCARD) {
return (short)POSN(i, 0);
}
}
return NOPOSN;
}
short FindHintedDest(short card, short hint)
{
unsigned char c;
if (hint == FOUNDATION) {
if (CanMoveOff((unsigned char)card))
return MOVEOFF;
else
return NOPOSN;
}
if (TYPE(card) != KING && hint != COL(cards[card])) {
c = column[hint];
if (c != NOCARD) {
while (next[c] != NOCARD)
c = next[c];
if (TYPE(c) == TYPE(card) + 1) {
return (short)POSN(COL(cards[c]), ROW(cards[c]) + 1);
}
}
}
if (ROW(cards[card]) == 0)
return NOPOSN;
if (column[hint] == NOCARD)
return (short)POSN(hint, 0);
return NOPOSN;
}
void MakeMove(unsigned char card, short dest)
{
short col, row, oldcol;
unsigned char c, i;
unsigned char h = 0;
if (dest == MOVEOFF) {
MoveOff(card);
return;
}
col = COL(dest);
row = ROW(dest);
oldcol = -1;
for (i = 0; oldcol == -1 && i < COLUMNS; i++) {
if (column[i] == card) {
column[i] = NOCARD;
oldcol = i;
}
}
for (i = 0; oldcol == -1 && i < NUMCARDS; i++) {
if (next[i] == card) {
if (hidden[i]) {
hidden[i] = 0;
h = 1;
}
next[i] = NOCARD;
oldcol = COL(cards[i]);
}
}
if (h)
AddUndo(U_MOVE_EXPOSE, card, cards[card]);
else
AddUndo(U_MOVE, card, cards[card]);
if (row > 0) {
c = column[col];
while (next[c] != NOCARD)
c = next[c];
next[c] = card;
}
else
column[col] = card;
while (card != NOCARD) {
cards[card] = POSN(col, row++);
card = next[card];
}
DisplayColumn(oldcol);
DisplayColumn(col);
return;
}
void FromStock()
{
unsigned char c, col, row;
if (stock != NOCARD) {
for (col = 0; col < COLUMNS; col++) {
if (column[col] == NOCARD) {
return;
}
}
for (col = 0; col < COLUMNS; col++) {
c = column[col];
row = 1;
while (next[c] != NOCARD) {
c = next[c];
row++;
}
next[c] = stock;
stock = next[stock];
cards[next[c]] = POSN(col, row);
next[next[c]] = NOCARD;
DisplayColumn((short)col);
}
if (stock == NOCARD)
DisplayStockPile();
AddUndo(U_FROMSTOCK, 0, 0);
}
return;
}
void MoveOff(unsigned char card)
{
unsigned char c, lastc;
unsigned char h = 0;
short oldcol;
oldcol = COL(cards[card]);
c = column[oldcol];
lastc = NOCARD;
while (hidden[c]) {
lastc = c;
c = next[c];
}
for (;;) {
while (c != NOCARD && TYPE(c) != KING && SUIT(c) != SUIT(card)) {
lastc = c;
c = next[c];
}
if (CheckFullTerminatingSuit(c)) {
if (lastc == NOCARD)
column[oldcol] = NOCARD;
else {
next[lastc] = NOCARD;
if (hidden[lastc]) {
hidden[lastc] = 0;
h = 1;
}
}
if (h)
AddUndo(U_MOVEOFF_EXPOSE, c, cards[c]);
else
AddUndo(U_MOVEOFF, c, cards[c]);
while (c != NOCARD) {
cards[c] = POSN(FOUNDATION, 0);
c = next[c];
}
if (foundation[SUIT(card)])
foundation[SUIT(card) + 4] = 1;
else
foundation[SUIT(card)] = 1;
DisplayFoundations();
DisplayColumn(oldcol);
return;
}
else {
lastc = c;
c = next[c];
}
}
}
short CanMoveOff(unsigned char card)
{
unsigned char c;
c = column[COL(cards[card])];
while (hidden[c])
c = next[c];
while (c != NOCARD) {
while (c != NOCARD && TYPE(c) != KING && SUIT(c) != SUIT(card))
c = next[c];
if (CheckFullTerminatingSuit(c))
return TRUE;
else
c = next[c];
}
return FALSE;
}
short CheckFullTerminatingSuit(unsigned char card)
{
unsigned char c;
short type;
c = card;
type = KING;
while (c != NOCARD && SUIT(c) == SUIT(card) && TYPE(c) == type) {
c = next[c];
type--;
}
if (c == NOCARD && type == ACE - 1)
return TRUE;
else
return FALSE;
}
void AddUndo(unsigned char type, unsigned char card, short from)
{
struct undo *undo;
undo = (struct undo *)malloc(sizeof(struct undo));
undo->type = type;
undo->card = card;
undo->from = from;
undo->next = undoinfo;
undoinfo = undo;
return;
}
void Undo()
{
struct undo *undo = undoinfo;
if (undo == NULL)
return;
switch (undo->type) {
case U_MOVE:
UndoMove(undo->card, (short)COL(undo->from), 0);
break;
case U_MOVE_EXPOSE:
UndoMove(undo->card, (short)COL(undo->from), 1);
break;
case U_MOVEOFF:
UndoMoveOff(undo->card, (short)COL(undo->from), 0);
break;
case U_MOVEOFF_EXPOSE:
UndoMoveOff(undo->card, (short)COL(undo->from), 1);
break;
case U_FROMSTOCK:
UndoFromStock();
break;
}
undoinfo = undoinfo->next;
free(undo);
return;
}
void UndoMove(unsigned char card, short col, unsigned char expose)
{
unsigned char c, row;
short oldcol;
oldcol = COL(cards[card]);
c = column[oldcol];
if (c == card) {
column[oldcol] = NOCARD;
} else {
while (next[c] != card)
c = next[c];
next[c] = NOCARD;
}
c = column[col];
row = 0;
if (c == NOCARD) {
column[col] = card;
cards[card] = POSN(col, row);
c = next[card];
} else {
while (next[c] != NOCARD) {
c = next[c];
row++;
}
if (expose)
hidden[c] = 1;
next[c] = card;
cards[card] = POSN(col, ++row);
c = next[card];
}
while (c != NOCARD) {
cards[c] = POSN(col, ++row);
c = next[c];
}
DisplayColumn(oldcol);
DisplayColumn(col);
return;
}
void UndoMoveOff(unsigned char card, short col, unsigned char expose)
{
unsigned char c, row;
c = column[col];
row = 0;
if (c == NOCARD) {
column[col] = card;
c = card;
while (c != NOCARD) {
cards[c] = POSN(col, row++);
c = next[c];
}
} else {
while (next[c] != NOCARD) {
c = next[c];
row++;
}
if (expose)
hidden[c] = 1;
next[c] = card;
c = next[c];
while (c != NOCARD) {
cards[c] = POSN(col, row++);
c = next[c];
}
}
if (foundation[SUIT(card) + 4])
foundation[SUIT(card) + 4] = 0;
else
foundation[SUIT(card)] = 0;
DisplayColumn((short)col);
DisplayFoundations();
return;
}
void UndoFromStock()
{
unsigned char oldstock = stock;
unsigned char c;
short col;
for (col = COLUMNS - 1; col >= 0; col--) {
c = column[col];
while (next[next[c]] != NOCARD) {
c = next[c];
}
next[next[c]] = stock;
stock = next[c];
cards[stock] = POSN(STOCK, 0);
next[c] = NOCARD;
DisplayColumn((short)col);
}
if (oldstock == NOCARD)
DisplayStockPile();
return;
}